var pageState = null;

function PageState(canvasx){
	this.t = null;
        this.context = canvasx.getContext("2d");
        this.canvas = canvasx;
        this.currStage= null;
	var ref = this;
	this.enable = null;
	this.disable = null;
	this.clicked = function(x,y){
	    return this.currStage.clicked(x,y);
	}
	this.clear = function () {
	    this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
	    var w = this.canvas.width;
	    this.canvas.width = 1;
	    this.canvas.width = w;
	}
        this.draw = function(stage,enable,disablex){
		if(this.t == null){
			this.disable = disablex;
			this.disable();
			this.disable = null;
			this.currStage = stage;
			this.enable = enable;
                 	this.t = setInterval(drawTimer,15);
		}
		
        }
	function drawTimer  ()
	{
        	ref.clear();
		if(ref.currStage != null){
			if(!ref.currStage.draw(ref)){
				if(ref.currStage.next!=null){
					ref.currStage = ref.currStage.next;
				}else{
        				clearInterval(ref.t);
					ref.t = null;
					if(ref.enable!=null){
						ref.enable();
					}
					ref.enable = null;
					ref.context.stroke();
					return;
				}	
			}
			ref.context.stroke();
		}
	}	

	
}
function DrawStage(elements){
	this.next= null;
	this.prev = null;
	this.elements = elements;
	this.clicked = function(x,y){
		for(i = 0; i < this.elements.length; i++){
		    if(this.elements[i].clicked(x,y)){
			return this.elements[i];
		    }
		}
		return null;
	}
	this.draw = function (pageState){
		if(this.prev != null){
			this.prev.draw(pageState);
		}
        	b = false;
	        for(i = 0; i < this.elements.length; i++){
        	         b = this.elements[i].draw(pageState) || b;
			 pageState.context.stroke();
        	}
		return b;
		
	}
}
function getPageState(canvas){
	if(pageState == null){
        	pageState = new PageState(canvas);
	}
	return pageState;
}

function ActionList() {
	this.actions = [];
	this.add = function(func){
		this.actions.push(func);
	}
	this.update = function(obj,pageState){
		if(this.actions.length > 0){
			if(!(this.actions[this.actions.length-1].update(obj, pageState))){
				this.actions.pop();
			}
			return true;
		}
		return false;
	}
}
function splitArr(textArr,pageWidth){
    ret = [];
    for(i = 0; i < textArr.length;i++){
        ret = ret.concat(splitLines(textArr[i],pageWidth));
    }
    return ret;
}
function splitLines(text,pageWidth){
		if(pageWidth == -1){
			return [text];
		}
		var diff = pageState.context.measureText(text).width -  pageWidth;
		if(diff > 0){
			//make a guess 
			var ind = 1;
			while(pageState.context.measureText(text.substring(0,ind))
                 .width<pageWidth&& text.length>ind){
				ind++;
			}
			while(text.charAt(ind) != " " && text.length>ind){
				ind++;
			}
			var textarr = [text.substring(0,ind)];
			if(text.length>ind){
				textarr= textarr.concat(splitLines(text.substring(ind+1,text.length),pageWidth));
				
			}
			return textarr;
			
		}else{
			return [text];
		}
}

function AText(text,x,y,fontStyle,fontSize,font,width) {
	var actions = new ActionList();
	this.addAction = function(func){
		actions.add(func);
	}
	this.text = splitArr(text,width)//pageState.context.width/2)
	this.x = x;
	this.y = y;
	this.fontSize = fontSize;
	this.fontStyle = fontStyle;
	this.font = font;
	this.dy = this.fontSize+3;
	this.updateFont = function (){
		this.style = this.fontStyle+" "+parseFloat(this.fontSize)+"px "+this.font; 	
	}

	this.style = this.updateFont(); 
	this.clear = function (pageState){

	}
	this.clicked = function (x,y){

		(new Line(this.x,this.y,this.x+this.fontSize*this.text.length,this.y,'black',5)).draw(pageState);
		(new Line(this.x,this.y -this.fontSize,this.x+this.fontSize*this.text.length,this.y-this.fontSize,'black',5)).draw(pageState);
	}
	this.height = function(){
		return this.text.length*this.dy
	}
	this.width= function(){
		return this.width
	}
	this.draw = function (pageState) {
	    
		ret  = actions.update(this,pageState);
		this.updateFont();
		pageState.context.font = this.style;
		//pageState.context.fillText(this.text,this.x,this.y);
		var curY = this.y;
		for(var i = 0; i < this.text.length; i++){
		    pageState.context.fillText(this.text[i],this.x,curY);
		    curY = curY + this.dy;
		}
		return ret;
	}
	
}
/*
function MultiLineText(text,x,y,fontStyle,fontSize,font) {
	var actions = new ActionList();
	this.addAction = function(func){
		actions.add(func);
	}
	this.text = text.split('\n');
	this.x = x;
	this.y = y;
	this.fontSize = fontSize;
	this.fontStyle = fontStyle;
	this.font = font;
	this.updateFont = function (){
		this.style = this.fontStyle+" "+parseFloat(this.fontSize)+"pt "+this.font; 	
	}

	this.style = this.updateFont(); 
	this.clear = function (pageState){

	}
	this.inObject = function (xpt,ypt, pageState){

	}
	
	this.draw = function (pageState) {
		ret  = actions.update(this,pageState);
		this.updateFont();
		pageState.context.font = this.style;
		
		var dy = 10;
		var curY = this.y;
		for(var i = 0; i < this.text.length; i++){
		    pageState.context.fillText(this.text[i],this.x,curY);
		    curY = curY + dy;
		}
		
		return ret;
	}
}
*/
function Color(r,g,b)
{
  this.Red = r;
  this.Green = g;
  this.Blue = b;

  this.HexString = function()
  {
    var rStr = this.Red.toString(16);
    if (rStr.length == 1)
      rStr = '0' + rStr;
    var gStr = this.Green.toString(16);
    if (gStr.length == 1)
      gStr = '0' + gStr;
    var bStr = this.Blue.toString(16);
    if (bStr.length == 1)
      bStr = '0' + bStr;
    return ('#' + rStr + gStr + bStr).toUpperCase();
  }
}
function FillColor(startColor) {
	this.addAction = function(func){
	}
	
	this.clicked = function (x,y){
	    return false;
	}
	this.draw = function (pageState) {
	pageState.context.fillStyle = startColor.HexString();
	pageState.context.strokeStyle = startColor.HexString();
	return false;
	    
	}
}
function DoStroke() {
	this.addAction = function(func){
	}
	
	this.clicked = function (x,y){
	    return false;
	}
	this.draw = function (pageState) {
	pageState.context.stroke();
	return false;
	    
	}
}
function ChangeColor(startColor, endColor, speed) {
	this.dr = speed/100.0*(endColor.Red-startColor.Red);
	this.dg = speed/100.0*(endColor.Green-startColor.Green);
	this.db = speed/100.0*(endColor.Blue-startColor.Blue);
	this.r = startColor.Red;
	this.g = startColor.Green;
	this.b = startColor.Blue;
	this.currColor = startColor;
	this.count = 0;
	this.addAction = function(func){
	}
	
	this.clicked = function (x,y){
	    return false;
	}
	this.draw = function (pageState) {
		if(this.count < 100){
		    this.count = this.count + 1;
		    this.r += this.dr;
		    this.g += this.dg;
		    this.b += this.db;
		    this.currColor.Red = Math.floor(this.r);
		    this.currColor.Blue = Math.floor(this.b);
		    this.currColor.Green = Math.floor(this.g);
		    //pageState.context.strokeStyle = this.currColor.HexString();
		    pageState.context.fillStyle= this.currColor.HexString();
		    return true;
		}else{
		    pageState.context.fillStyle = endColor.HexString();
		    //pageState.context.strokeStyle = endColor.HexString();
		    return false;
		}
	}
}
function FontSizeAction(objp,toFontSize,speed){
	this.df = speed/100.0*(toFontSize-objp.fontSize);
	this.ret = true;
	this.update = function (obj, pageState){
		obj.fontSize = obj.fontSize + this.df;
		if(this.df > 0){
			if(obj.fontSize > toFontSize){
				obj.fontSize = toFontSize;
				this.ret = false;
			}
		}else{
			if(obj.fontSize < toFontSize){
				obj.fontSize = toFontSize
				this.ret = false;
			}
		}	
		return this.ret;
	}
}

function TextMoveAction(objp,toX,toY,speed){
//distance to travel in x 
	this.dx = speed/100.0*(toX-objp.x);// speed/100*(toX-obj.x
	this.dy = speed/100.0*(toY-objp.y);
	this.update = function (obj, pageState){
		obj.x = obj.x+ this.dx;
		obj.y = obj.y+this.dy;
		if(this.dx > 0){
			if(obj.x > toX){
				obj.x = toX;
				obj.y = toY;
				return false;
			}
		}else{
			if(obj.x < toX){
				obj.x = toX;
				obj.y = toY;
				return false;
			}
		}	
		return true;
	}
}

function AndAction(andActions){
	actions = andActions;
	this.update = function(obj,pageState){
		b = false;
		for(i = 0; i < actions.length; i++){
			b =  actions[i].update(obj,pageState) || b;
		}
		return b;
	}
}

function Line(x1,y1,x2,y2,strokeStyle,lineWidth){
	var actions = new ActionList();
	this.x1 = x1;
	this.x2 = x2;
	this.y1 = y1;
	this.y2 = y2;
	this.strokeStyle = strokeStyle;
	this.lineWidth = lineWidth;
	this.addAction = function(func){
		actions.add(func);
	}
	
	this.clicked = function (x,y){
	    return false;
	}
	this.draw = function(pageContext){

		ret  = actions.update(this,pageState);
	
		pageState.context.strokeStyle= this.strokeStyle;
		pageState.context.moveTo(this.x1,this.y1);
		pageState.context.lineTo(this.x2,this.y2);
		return ret;
	}
}
function LineMoveAction(x1,y1,x2,y2,speed,line){
	this.timeStep = speed/100.0;
	this.time = 0;
	this.dx1 = this.timeStep*(x1-line.x1);
	this.dy1 = this.timeStep* (y1-line.y1);
	this.dx2 = this.timeStep*(x2-line.x2);
	this.dy2 = this.timeStep* (y2-line.y2);
	this.update = function (obj, pageState){
		if(this.time >.99){
			obj.x1 = x1;
			obj.x2 = x2;
			obj.y1 = y1;
			obj.y2 = y2;
			return false;
		}

		obj.x1 = obj.x1+ this.dx1;
		obj.x2 = obj.x2+ this.dx2;
		obj.y1 = obj.y1+ this.dy1;
		obj.y2 = obj.y2+ this.dy2;
		this.time = this.time + this.timeStep;
		return true;
	}

}
